package com.jdrx.sw.sewage.service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jdrx.sw.sewage.beans.dto.CdAiLogQueryDTO;
import com.jdrx.sw.sewage.beans.dto.CdParamUpdateDTO;
import com.jdrx.sw.sewage.beans.dto.CdRunCurveDTO;
import com.jdrx.sw.sewage.beans.entity.CdAiLogPO;
import com.jdrx.sw.sewage.beans.entity.CdParamPO;
import com.jdrx.sw.sewage.beans.vo.CdAerationDataVO;
import com.jdrx.sw.sewage.beans.vo.CdRunCurveVO;
import com.jdrx.sw.sewage.beans.vo.GatherDevPointOptionVO;
import com.jdrx.sw.sewage.dao.CdAerationDataDAO;
import com.jdrx.sw.sewage.dao.CdAiLogDAO;
import com.jdrx.sw.sewage.dao.CdForecastDataDAO;
import com.jdrx.sw.sewage.dao.CdParamDAO;
import com.jdrx.sw.sewage.dao.CdRealtimeDataDAO;
import com.jdrx.sw.sewage.dao.GatherDevPointDAO;

/**
 * 智能碳源加药demo
 * @author Administrator
 *
 */
@Service
public class ChemicalDosingService {
	@Autowired
	private CdAiLogDAO cdAiLogDAO;
	@Autowired
	private CdRealtimeDataDAO cdRealtimeDataDAO;
	@Autowired
	private CdParamDAO cdParamDAO;
	@Autowired
	private CdForecastDataDAO cdForecastDataDAO;
	@Autowired
	private CdAerationDataDAO cdAerationDataDAO;
	@Autowired
	private GatherDevPointDAO gatherDevPointDAO;
	
	public List<CdAiLogPO> aiLogList(CdAiLogQueryDTO dto) {
		CdAiLogPO po = new CdAiLogPO();
		BeanUtils.copyProperties(dto, po);
		return cdAiLogDAO.list(po);
	}
	
	public Map<String, List<GatherDevPointOptionVO>> latestRealtimeData() {
		// 进水口实时数据
		List<GatherDevPointOptionVO> jsk = gatherDevPointDAO.findByValues(Lists.newArrayList("JSK_NH3NY_NH3N_Y", "JSK_PHY_PH_Y", "JSK_SSY_SS_Y", "JSK_TNY_TN_Y", "JSK_TPY_TP_Y", "JSK_WDJ_WD_Y", "JSK_CODY_COD_Y"));
		// 一厂一期生化池实时数据
		List<GatherDevPointOptionVO> shc = gatherDevPointDAO.findByValues(Lists.newArrayList("SHC1_DOY1_DO_Y", "SHC1_DOY2_DO_Y", "SHC1_MLSSY1_MLSS_Y", "SHC1_MLSSY2_MLSS_Y", "SHC1_ORPY1_ORP_Y", "SHC1_ORPY2_ORP_Y"));
		// 一厂碳源加药间流量
		List<GatherDevPointOptionVO> ty = gatherDevPointDAO.findByValues(Lists.newArrayList("TYJY1_LLJ1_SSLL_Y", "TYJY1_LLJ2_SSLL_Y", "TYJY1_LLJ3_SSLL_Y", "TYJY1_LLJ5_SSLL_Y", "TYJY1_LLJ6_SSLL_Y", "TYJY1_LLJ7_SSLL_Y"));
		// 出水口实时数据
		List<GatherDevPointOptionVO> csk = gatherDevPointDAO.findByValues(Lists.newArrayList("CSQ_CODY_COD_Y", "CSQ_NH3NY_NH3N_Y", "CSQ_NOY_NO_Y", "CSQ_PHY_PH_Y", "CSQ_SSY_SS_Y", "CSQ_TNY_TN_Y", "CSQ_TPY_TP_Y", "CSQ_WDJ_WD_Y"));
		
		Map<String, List<GatherDevPointOptionVO>> map = Maps.newHashMap();
		map.put("jsk", jsk);
		map.put("shc", shc);
		map.put("ty", ty);
		map.put("csk", csk);
		return map;
	}
	
	public Map<String, CdParamPO> param() {
		List<CdParamPO> list = cdParamDAO.listAll();
		return list.stream().collect(Collectors.toMap(CdParamPO :: getName, Function.identity(), (key1, key2) -> key2));
	}
	
	public void updateParam(CdParamUpdateDTO dto) {
		CdParamPO po = new CdParamPO();
		BeanUtils.copyProperties(dto, po);
		cdParamDAO.update(po);
	}
	
	public Map<String, Object> runCurve(CdRunCurveDTO dto) {
		// 实时数据列表
		List<CdRunCurveVO> realtimeDataList = cdRealtimeDataDAO.listByintervalTime("碳源", dto.getStartDataTime(), dto.getEndDataTime());
		// AI加药列表
		List<CdRunCurveVO> forecastDataList = cdForecastDataDAO.listByintervalTime("碳源", dto.getStartDataTime(), dto.getEndDataTime());
		
		// 将具体点位数据集合转为以时间为键的对象map集合
		Map<LocalDateTime, CdRunCurveVO> realtimeDataMap = realtimeDataList.stream()
				.collect(Collectors.toMap(CdRunCurveVO::getIntervalTime, Function.identity(), (key1, key2) -> key2));
		Map<LocalDateTime, CdRunCurveVO> forecastDataMap = forecastDataList.stream()
				.collect(Collectors.toMap(CdRunCurveVO::getIntervalTime, Function.identity(), (key1, key2) -> key2));
		
		// 临时集合，用于比较取数据最多的集合作为基准展示时间、数据
		List<CdRunCurveVO> tempList = realtimeDataList.size() > forecastDataList.size() ? realtimeDataList : forecastDataList;
		Map<String, Object> dataMap = null;
		List<Map<String, Object>> dataList = Lists.newArrayList();
		for(CdRunCurveVO vo : tempList) {
			dataMap = Maps.newHashMap();
			dataMap.put("intervalTime", vo.getIntervalTime());
			dataMap.put("realtimeData", Optional.ofNullable(realtimeDataMap.get(vo.getIntervalTime())).map(t->t.getValue()).orElse(null));
			dataMap.put("forecastData", Optional.ofNullable(forecastDataMap.get(vo.getIntervalTime())).map(t->t.getValue()).orElse(null));
			dataList.add(dataMap);
		}
		
		// 结算节省药剂百分比=(自控总和-AI总和)/自控总和
		// 自控总和
		BigDecimal realtimeData = realtimeDataList.stream()
				.filter(p -> NumberUtils.isCreatable(p.getValue()))
				.map(p -> new BigDecimal(p.getValue()))
				.reduce(BigDecimal.ZERO, BigDecimal::add);
		// AI总和
		BigDecimal forecastData = forecastDataList.stream()
				.filter(p -> NumberUtils.isCreatable(p.getValue()))
				.map(p -> new BigDecimal(p.getValue()))
				.reduce(BigDecimal.ZERO, BigDecimal::add);
		// 百分比
		double percent = 1;
		if(realtimeData.compareTo(BigDecimal.ZERO) != 0 && forecastData.compareTo(BigDecimal.ZERO) != 0) {
			percent = realtimeData.subtract(forecastData)
					.divide(realtimeData, BigDecimal.ROUND_HALF_UP)
					.setScale(3, BigDecimal.ROUND_DOWN)
					.doubleValue();
		}
		Map<String, Object> result = Maps.newHashMap();
		result.put("dataList", dataList);
		result.put("percent", percent);
		return result;
	}
	
	/**
	 * 曝气分析数据折线对比图
	 * @return
	 */
	public Map<String, Object> runAerationCurve(CdRunCurveDTO dto) {
		List<CdAerationDataVO> list = cdAerationDataDAO.list(dto.getStartDataTime(), dto.getEndDataTime());
		
		// 对比值计算=(自控总和-AI总和)/自控总和
		BigDecimal realtimeData = new BigDecimal(0);// 自控总和
		BigDecimal forecastData = new BigDecimal(0);// AI总和
		for(CdAerationDataVO vo : list) {
			if(NumberUtils.isCreatable(vo.getRealtimeData())) {
				realtimeData = realtimeData.add(new BigDecimal(vo.getRealtimeData()));
			}
			if(NumberUtils.isCreatable(vo.getForecastData())) {
				forecastData = forecastData.add(new BigDecimal(vo.getForecastData()));
			}
		}
		// 百分比
		double percent = 100;
		if(realtimeData != null && realtimeData.compareTo(BigDecimal.ZERO) == 1
				&& forecastData != null && forecastData.compareTo(BigDecimal.ZERO) == 1) {
			percent = realtimeData.subtract(forecastData).divide(realtimeData, BigDecimal.ROUND_HALF_UP).setScale(3, BigDecimal.ROUND_DOWN).doubleValue();
		}
		
		Map<String, Object> result = Maps.newHashMap();
		result.put("dataList", list);
		result.put("percent", percent);
		return result;
	}
}